"""
供应链采购管理优化模块
提供供应商管理、采购优化、合同分析等功能
"""

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from typing import Dict, List, Tuple, Optional
import warnings
warnings.filterwarnings('ignore')

class SupplierManager:
    """供应商管理核心类"""
    
    def __init__(self):
        self.supplier_metrics = [
            'quality_score', 'delivery_score', 'cost_score', 'service_score', 'compliance_score'
        ]
        self.weights = {
            'quality_score': 0.3,
            'delivery_score': 0.25,
            'cost_score': 0.2,
            'service_score': 0.15,
            'compliance_score': 0.1
        }
        
        # TODO: [供应商管理优化] - 增强供应商评估和管理能力
        # 业务需求:
        # 1. 实现动态权重调整，根据业务优先级自动调整评分权重
        # 2. 添加供应商风险评估模型，包括财务风险、地缘政治风险
        # 3. 实现供应商生命周期管理，从准入到退出的全流程管理
        # 4. 建立供应商协同平台，实现信息共享和协同计划
        # 技术实现:
        # 1. 使用机器学习算法动态优化权重配置
        # 2. 集成外部数据源进行风险监控和预警
        # 3. 建立供应商画像和分类管理体系
        # 4. 开发供应商门户和API接口
    
    def calculate_supplier_kpis(self, supplier_data: pd.DataFrame, 
                              orders_data: pd.DataFrame, 
                              quality_data: pd.DataFrame) -> pd.DataFrame:
        """
        计算供应商关键绩效指标
        
        Args:
            supplier_data: 供应商基本信息
            orders_data: 采购订单数据
            quality_data: 质量数据
            
        Returns:
            pd.DataFrame: 供应商KPI评分表
        """
        
        # TODO: [KPI计算优化] - 提升供应商绩效评估准确性
        # 业务需求:
        # 1. 增加更多维度的KPI指标（创新能力、可持续性、数字化水平）
        # 2. 实现行业基准对比和相对排名
        # 3. 添加趋势分析和预测性评估
        # 4. 支持多层级供应商评估（一级、二级供应商）
        # 技术实现:
        # 1. 扩展KPI计算框架，支持自定义指标
        # 2. 集成行业数据库进行基准对比
        # 3. 使用时间序列分析预测供应商表现
        # 4. 建立供应商网络分析和风险传导模型
        supplier_kpis = []
        
        for supplier_id in supplier_data['supplier_id'].unique():
            supplier_orders = orders_data[orders_data['supplier_id'] == supplier_id]
            supplier_quality = quality_data[quality_data['supplier_id'] == supplier_id]
            
            if len(supplier_orders) == 0:
                continue
            
            # 1. 质量评分 (基于不良率)
            total_qty = supplier_orders['quantity'].sum()
            defective_qty = supplier_quality['defective_quantity'].sum() if len(supplier_quality) > 0 else 0
            defect_rate = defective_qty / total_qty if total_qty > 0 else 0
            quality_score = max(0, 100 - (defect_rate * 1000))  # 不良率转换为0-100分
            
            # TODO: 增强质量评分算法
            # 1. 考虑质量改进趋势和持续改善能力
            # 2. 添加客户投诉和退货率指标
            # 3. 集成质量认证和体系评估
            
            # 2. 交付评分 (基于准时交付率)
            on_time_orders = supplier_orders[
                supplier_orders['actual_delivery_date'] <= supplier_orders['promised_delivery_date']
            ]
            on_time_rate = len(on_time_orders) / len(supplier_orders) if len(supplier_orders) > 0 else 0
            delivery_score = on_time_rate * 100
            
            # TODO: 优化交付评分模型
            # 1. 考虑交付时间的稳定性和可预测性
            # 2. 添加紧急订单响应能力评估
            # 3. 集成物流跟踪和可视化数据
            
            # 3. 成本评分 (基于价格竞争力)
            avg_price = supplier_orders['unit_price'].mean()
            market_avg_price = orders_data['unit_price'].mean()
            cost_ratio = avg_price / market_avg_price if market_avg_price > 0 else 1
            cost_score = max(0, 100 - ((cost_ratio - 1) * 50))  # 价格高于市场平均则扣分
            
            # TODO: 完善成本评估体系
            # 1. 考虑总拥有成本（TCO）而非单纯采购价格
            # 2. 添加价格稳定性和透明度评估
            # 3. 集成成本节约贡献和价值创造能力
            
            # 4. 服务评分 (基于响应时间)
            avg_response_time = supplier_orders['response_time_days'].mean()
            service_score = max(0, 100 - (avg_response_time * 5))  # 响应时间扣分
            
            # TODO: 扩展服务评价维度
            # 1. 添加技术支持和售后服务评估
            # 2. 考虑沟通效率和协作能力
            # 3. 集成客户满意度调研结果
            
            # 5. 合规评分 (基于合同履约)
            compliant_orders = supplier_orders[supplier_orders['contract_compliance'] == True]
            compliance_rate = len(compliant_orders) / len(supplier_orders) if len(supplier_orders) > 0 else 0
            compliance_score = compliance_rate * 100
            
            # TODO: 强化合规管理
            # 1. 集成ESG（环境、社会、治理）评估
            # 2. 添加法律法规合规性检查
            # 3. 建立供应商审计和认证体系
            
            # 综合评分
            composite_score = (
                quality_score * self.weights['quality_score'] +
                delivery_score * self.weights['delivery_score'] +
                cost_score * self.weights['cost_score'] +
                service_score * self.weights['service_score'] +
                compliance_score * self.weights['compliance_score']
            )
            
            supplier_kpis.append({
                'supplier_id': supplier_id,
                'quality_score': round(quality_score, 2),
                'delivery_score': round(delivery_score, 2),
                'cost_score': round(cost_score, 2),
                'service_score': round(service_score, 2),
                'compliance_score': round(compliance_score, 2),
                'composite_score': round(composite_score, 2),
                'supplier_grade': self._get_supplier_grade(composite_score)
            })
        
        return pd.DataFrame(supplier_kpis)
    
    def _get_supplier_grade(self, score: float) -> str:
        """根据综合评分确定供应商等级"""
        if score >= 90:
            return 'A'
        elif score >= 80:
            return 'B'
        elif score >= 70:
            return 'C'
        elif score >= 60:
            return 'D'
        else:
            return 'E'
    
    def identify_risk_suppliers(self, supplier_kpis: pd.DataFrame, 
                              risk_threshold: float = 70.0) -> pd.DataFrame:
        """识别高风险供应商"""
        risk_suppliers = supplier_kpis[
            supplier_kpis['composite_score'] < risk_threshold
        ].copy()
        
        risk_suppliers['risk_level'] = risk_suppliers['composite_score'].apply(
            lambda x: '高风险' if x < 60 else '中风险'
        )
        
        return risk_suppliers.sort_values('composite_score')

class ProcurementOptimizer:
    """采购优化核心类"""
    
    def __init__(self):
        self.holding_cost_rate = 0.2  # 年库存持有成本率
        self.ordering_cost = 100  # 单次订货成本
    
    def calculate_eoq(self, annual_demand: float, unit_cost: float, 
                     ordering_cost: float = None, holding_cost_rate: float = None) -> Dict:
        """
        计算经济订货批量(EOQ)
        
        Args:
            annual_demand: 年需求量
            unit_cost: 单位成本
            ordering_cost: 单次订货成本
            holding_cost_rate: 库存持有成本率
            
        Returns:
            dict: EOQ计算结果
        """
        if ordering_cost is None:
            ordering_cost = self.ordering_cost
        if holding_cost_rate is None:
            holding_cost_rate = self.holding_cost_rate
        
        holding_cost_per_unit = unit_cost * holding_cost_rate
        
        if holding_cost_per_unit <= 0:
            return {'eoq': annual_demand, 'total_cost': float('inf')}
        
        # EOQ公式
        eoq = np.sqrt((2 * annual_demand * ordering_cost) / holding_cost_per_unit)
        
        # 计算相关成本
        ordering_cost_total = (annual_demand / eoq) * ordering_cost
        holding_cost_total = (eoq / 2) * holding_cost_per_unit
        purchase_cost = annual_demand * unit_cost
        total_cost = ordering_cost_total + holding_cost_total + purchase_cost
        
        return {
            'eoq': round(eoq, 0),
            'ordering_cost': round(ordering_cost_total, 2),
            'holding_cost': round(holding_cost_total, 2),
            'purchase_cost': round(purchase_cost, 2),
            'total_cost': round(total_cost, 2),
            'orders_per_year': round(annual_demand / eoq, 1),
            'cycle_time_days': round(365 / (annual_demand / eoq), 1)
        }
    
    def optimize_procurement_batch(self, demand_forecast: pd.Series, 
                                 unit_cost: float, lead_time_days: int = 7,
                                 service_level: float = 0.95) -> Dict:
        """
        优化采购批次
        
        Args:
            demand_forecast: 需求预测序列
            unit_cost: 单位成本
            lead_time_days: 采购提前期
            service_level: 服务水平
            
        Returns:
            dict: 优化结果
        """
        if len(demand_forecast) == 0:
            return {}
        
        # 计算统计参数
        avg_daily_demand = demand_forecast.mean()
        std_daily_demand = demand_forecast.std()
        
        # 年需求量估算
        annual_demand = avg_daily_demand * 365
        
        # 计算EOQ
        eoq_result = self.calculate_eoq(annual_demand, unit_cost)
        
        # 计算安全库存
        from scipy.stats import norm
        z_score = norm.ppf(service_level)
        safety_stock = z_score * std_daily_demand * np.sqrt(lead_time_days)
        
        # 再订货点
        reorder_point = avg_daily_demand * lead_time_days + safety_stock
        
        # 最大库存
        max_stock = reorder_point + eoq_result['eoq']
        
        return {
            'avg_daily_demand': round(avg_daily_demand, 2),
            'annual_demand': round(annual_demand, 0),
            'eoq': eoq_result['eoq'],
            'safety_stock': round(safety_stock, 0),
            'reorder_point': round(reorder_point, 0),
            'max_stock': round(max_stock, 0),
            'service_level': service_level,
            'lead_time_days': lead_time_days
        }
    
    def analyze_procurement_savings(self, current_orders: pd.DataFrame,
                                  optimized_orders: pd.DataFrame) -> Dict:
        """分析采购优化带来的成本节约"""
        
        # 当前成本
        current_total_cost = current_orders['total_cost'].sum()
        
        # 优化后成本
        optimized_total_cost = optimized_orders['total_cost'].sum()
        
        # 节约计算
        cost_savings = current_total_cost - optimized_total_cost
        savings_percentage = (cost_savings / current_total_cost) * 100 if current_total_cost > 0 else 0
        
        return {
            'current_total_cost': round(current_total_cost, 2),
            'optimized_total_cost': round(optimized_total_cost, 2),
            'cost_savings': round(cost_savings, 2),
            'savings_percentage': round(savings_percentage, 2)
        }
    
    def calculate_procurement_needs(self, inventory_df: pd.DataFrame) -> pd.DataFrame:
        """
        计算采购需求建议
        
        Args:
            inventory_df: 库存数据DataFrame
            
        Returns:
            pd.DataFrame: 采购建议列表
        """
        if inventory_df.empty:
            return pd.DataFrame()
        
        # 按产品聚合库存总量
        product_inventory = inventory_df.groupby('product_id').agg({
            'quantity': 'sum',
            'warehouse_id': 'first',  # 使用第一个仓库作为默认
            'status': lambda x: '可用' if '可用' in x.values else x.iloc[0]  # 优先可用状态
        }).reset_index()
        
        # 筛选低库存产品
        low_stock_threshold = 20  # 低库存阈值
        low_stock_products = product_inventory[
            (product_inventory['quantity'] < low_stock_threshold) & 
            (product_inventory['status'] == '可用')
        ].copy()
        
        if low_stock_products.empty:
            return pd.DataFrame()
        
        # 计算采购建议
        procurement_needs = []
        
        for _, product in low_stock_products.iterrows():
            # 计算建议采购量
            current_stock = product['quantity']
            target_stock = max(50, low_stock_threshold * 2)  # 目标库存
            suggested_order = target_stock - current_stock
            
            if suggested_order <= 0:
                continue
            
            # 估算成本（使用默认价格或从其他数据源获取）
            unit_cost = 10.0  # 默认单价
            estimated_cost = suggested_order * unit_cost
            
            # 计算优先级分数（库存越低优先级越高）
            stock_ratio = current_stock / low_stock_threshold
            priority_score = max(0, 100 - (stock_ratio * 100))
            
            procurement_needs.append({
                'product_id': product['product_id'],
                'product_name': product['product_id'],  # 暂时使用product_id作为名称
                'current_quantity': current_stock,
                'suggested_order_quantity': suggested_order,
                'estimated_cost': round(estimated_cost, 2),
                'supplier_id': '默认供应商',
                'priority_score': round(priority_score, 2),
                'urgency_level': '高' if priority_score > 80 else '中' if priority_score > 50 else '低'
            })
        
        return pd.DataFrame(procurement_needs)

class ContractAnalyzer:
    """合同分析核心类"""
    
    def __init__(self):
        self.contract_types = ['fixed_price', 'cost_plus', 'time_materials', 'performance_based']
    
    def analyze_contract_performance(self, contracts_df: pd.DataFrame, 
                                 actual_orders: pd.DataFrame) -> pd.DataFrame:
        """
        分析合同履约情况
        
        Args:
            contracts_df: 合同数据
            actual_orders: 实际订单数据
            
        Returns:
            pd.DataFrame: 合同履约分析结果
        """
        contract_analysis = []
        
        for _, contract in contracts_df.iterrows():
            contract_orders = actual_orders[
                (actual_orders['supplier_id'] == contract['supplier_id']) &
                (actual_orders['order_date'] >= contract['start_date']) &
                (actual_orders['order_date'] <= contract['end_date'])
            ]
            
            if len(contract_orders) == 0:
                continue
            
            # 合同履约率
            compliant_orders = contract_orders[contract_orders['contract_compliance'] == True]
            compliance_rate = len(compliant_orders) / len(contract_orders)
            
            # 合同金额完成率
            actual_amount = contract_orders['total_amount'].sum()
            contracted_amount = contract['contract_amount']
            completion_rate = actual_amount / contracted_amount if contracted_amount > 0 else 0
            
            # 价格差异分析
            avg_contract_price = contract['unit_price']
            avg_actual_price = contract_orders['unit_price'].mean()
            price_variance = ((avg_actual_price - avg_contract_price) / avg_contract_price * 100) if avg_contract_price > 0 else 0
            
            # 交付表现
            on_time_rate = len(contract_orders[
                contract_orders['actual_delivery_date'] <= contract_orders['promised_delivery_date']
            ]) / len(contract_orders) if len(contract_orders) > 0 else 0
            
            contract_analysis.append({
                'contract_id': contract['contract_id'],
                'supplier_id': contract['supplier_id'],
                'compliance_rate': round(compliance_rate * 100, 2),
                'completion_rate': round(completion_rate * 100, 2),
                'price_variance': round(price_variance, 2),
                'on_time_rate': round(on_time_rate * 100, 2),
                'contract_status': self._get_contract_status(completion_rate, compliance_rate)
            })
        
        return pd.DataFrame(contract_analysis)
    
    def _get_contract_status(self, completion_rate: float, compliance_rate: float) -> str:
        """确定合同状态"""
        if completion_rate >= 0.9 and compliance_rate >= 0.9:
            return '优秀'
        elif completion_rate >= 0.8 and compliance_rate >= 0.8:
            return '良好'
        elif completion_rate >= 0.7 and compliance_rate >= 0.7:
            return '一般'
        else:
            return '需关注'
    
    def calculate_contract_risk(self, contract_analysis: pd.DataFrame) -> pd.DataFrame:
        """计算合同风险评分"""
        risk_factors = ['compliance_rate', 'completion_rate', 'on_time_rate']
        
        # 风险评分计算（反向指标）
        contract_analysis['risk_score'] = (
            (100 - contract_analysis['compliance_rate']) * 0.4 +
            (100 - contract_analysis['completion_rate']) * 0.3 +
            abs(contract_analysis['price_variance']) * 0.2 +
            (100 - contract_analysis['on_time_rate']) * 0.1
        )
        
        # 风险等级
        contract_analysis['risk_level'] = pd.cut(
            contract_analysis['risk_score'],
            bins=[0, 20, 40, 60, 100],
            labels=['低风险', '中低风险', '中高风险', '高风险']
        )
        
        return contract_analysis.sort_values('risk_score', ascending=False)

class ProcurementDashboard:
    """采购管理仪表板"""
    
    def __init__(self):
        self.supplier_manager = SupplierManager()
        self.optimizer = ProcurementOptimizer()
        self.contract_analyzer = ContractAnalyzer()
    
    def generate_procurement_summary(self, supplier_data: pd.DataFrame,
                                   orders_data: pd.DataFrame,
                                   quality_data: pd.DataFrame,
                                   contracts_data: pd.DataFrame) -> Dict:
        """生成采购管理综合报告"""
        
        # 供应商绩效分析
        supplier_kpis = self.supplier_manager.calculate_supplier_kpis(
            supplier_data, orders_data, quality_data
        )
        
        # 合同履约分析
        contract_analysis = self.contract_analyzer.analyze_contract_performance(
            contracts_data, orders_data
        )
        
        # 风险供应商识别
        risk_suppliers = self.supplier_manager.identify_risk_suppliers(supplier_kpis)
        
        # 合同风险分析
        contract_risk = self.contract_analyzer.calculate_contract_risk(contract_analysis)
        
        return {
            'supplier_performance': supplier_kpis,
            'contract_analysis': contract_analysis,
            'risk_suppliers': risk_suppliers,
            'contract_risk': contract_risk,
            'summary_metrics': {
                'total_suppliers': len(supplier_kpis),
                'grade_a_suppliers': len(supplier_kpis[supplier_kpis['supplier_grade'] == 'A']),
                'risk_suppliers_count': len(risk_suppliers),
                'avg_compliance_rate': contract_analysis['compliance_rate'].mean(),
                'high_risk_contracts': len(contract_risk[contract_risk['risk_level'] == '高风险'])
            }
        }